package networkTraining.epoch;

import java.util.HashMap;
import java.util.Map;

import networkTraining.INetworkTrainer;
import networkTraining.IDataSet;
import neuralNetwork.INeuralNetwork;
import neuralNetwork.execution.INeuralNetworkExecutor;
import neuralNetwork.execution.NeuralNetworkExecutor;

public class TestingEpoch extends EpochExecutorBase
{
	private INeuralNetworkExecutor neuralNetworkExecutor;
	private Map<String, Double> localErrorMap;

	public TestingEpoch()
	{
		neuralNetworkExecutor = new NeuralNetworkExecutor();
		localErrorMap = new HashMap<String, Double>();
	}

	@Override
	public void executeEpoch()
	{
		resetErrors();

		neuralNetworkExecutor.setNeuralNetwork(getNetworkTrainer().getNeuralNetwork());
		INetworkTrainer networkTrainer = getNetworkTrainer();
		INeuralNetwork neuralNetwork = networkTrainer.getNeuralNetwork();
		IDataSet dataSet = networkTrainer.getDataSetProvider().getTestingData();

		for (int row = 0; row < dataSet.getDataSetSize(); row++)
		{
			// setup input sensors
			for (String name : dataSet.getInputNeuronNames())
				neuralNetwork.getNeuron(name).setOutputValue(dataSet.getInputValueForRow(name, row));

			// run the simulation until 
			for (int i = 0; i <= neuralNetwork.getLayerCount(); i++)
				neuralNetworkExecutor.performTimeStep();

			for (String outputName : dataSet.getOutputNeuronNames())
			{
				double actualOutput = neuralNetwork.getNeuron(outputName).getOutputValue();
				double error = dataSet.getExpectedOutputValueForRow(outputName, row) - actualOutput;
				localErrorMap.put(outputName, error);
			}
			updateErrorSums(localErrorMap);
		}

		calculateEpochErrors(dataSet);
	}

}
